package org.jetlinks.pro.rule.engine.editor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

@Slf4j
public abstract class AbstractEditorNode implements EditorNode {

    private final Map<ResourceType, LocaleResourceResolver> localeResources = new HashMap<>();

    public AbstractEditorNode() {

    }


    public final void setResource(ResourceType type, String resourceLocation) {
        localeResources.computeIfAbsent(type, __ -> new LocaleResourceResolver())
                       .setPath(resourceLocation);

    }

    @Override
    public final Set<String> getTypes() {
        return Collections.singleton(getId());
    }

    @Override
    public final Map<ResourceType, Resource> getEditorResources() {
        return getEditorResources(Locale.getDefault());
    }

    @Override
    public final Map<ResourceType, Resource> getEditorResources(Locale locale) {
        Map<ResourceType, Resource> resourceMap = new HashMap<>();
        for (Map.Entry<ResourceType, LocaleResourceResolver> entry : localeResources.entrySet()) {
            Resource resource = entry.getValue().apply(locale);
            if (null != resource) {
                resourceMap.put(entry.getKey(), resource);
            }
        }
        return resourceMap;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public abstract int getOrder();

    private static class LocaleResourceResolver implements Function<Locale, Resource> {

        private String path;
        private Resource defaultResource;
        private final Map<Locale, Resource> cached = new ConcurrentHashMap<>();

        public void setPath(String path) {
            this.path = path;
            this.defaultResource = resolve(Locale.getDefault(), path);
        }

        private Resource resolve(Locale locale, String resourcePath) {
            String realPath = resourcePath
                .replace("{language}", locale.getLanguage())
                .replace("{country}", locale.getCountry())
                .replace("{locale}", locale.toString().replace("_","-"));
            Resource resource = new ClassPathResource(realPath, ClassUtils.getDefaultClassLoader());
            if(!resource.exists()){
                log.warn("No Resource for RueEngine Editor");
            }
            return resource;
        }

        @Override
        public Resource apply(Locale locale) {
            return cached
                .computeIfAbsent(locale, _locale -> {
                    if (StringUtils.isEmpty(path)) {
                        return null;
                    }
                    Resource resource = resolve(_locale, path);
                    if (!resource.exists()) {
                        if (defaultResource != null) {
                            return defaultResource;
                        }
                    }
                    return resource;
                });
        }
    }
}
